package com.km.metric;

import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.httpclient.HttpStatus;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PrivateHttpClient {
	private static final Logger log = LoggerFactory.getLogger(PrivateHttpClient.class);
	private static final String DEFAULT_ENCODING = "UTF-8";
	private static RequestConfig fastRequestConfig;
	private final int MAX_SOCKET_TIMEOUT = 3000;
	private final int MAX_CONNECTION_TIMEOUT = 300;
	private static HttpClientConnectionManager connManager;
	private static SSLConnectionSocketFactory connectFactory;
	private static HttpRequestRetryHandler noRetryHandler = new HttpRequestRetryHandler() {

		public boolean retryRequest(IOException arg0, int arg1, HttpContext arg2) {
			return false;
		}
	};
	{
		// normal request config
		connManager = createConnectManager();
		connectFactory = createSSLConnSocketFactory();

		RequestConfig.Builder fastConfigBuilder = RequestConfig.custom();
		// 设置连接超时
		fastConfigBuilder.setConnectTimeout(MAX_CONNECTION_TIMEOUT);
		// 设置读取超时
		fastConfigBuilder.setSocketTimeout(MAX_SOCKET_TIMEOUT);
		// 设置从连接池获取连接实例的超时
		fastConfigBuilder.setConnectionRequestTimeout(MAX_CONNECTION_TIMEOUT);
		// // 在提交请求之前 测试连接是否可用
		// configBuilder.setStaleConnectionCheckEnabled(true);
		fastRequestConfig = fastConfigBuilder.build();

	}

	private HttpClientConnectionManager createConnectManager() {
		try {
			PoolingHttpClientConnectionManager connectManager = new PoolingHttpClientConnectionManager();
			SSLContext sslContext = SSLContext.getInstance("SSLv3");
			// 实现一个X509TrustManager接口，用于绕过验证，不用修改里面的方法
			X509TrustManager trustManager = new X509TrustManager() {
				public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {

				}

				public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {

				}

				public X509Certificate[] getAcceptedIssuers() {
					return null;
				}

			};

			sslContext.init(null, new TrustManager[] { trustManager }, null);

			// 设置协议http和https对应的处理socket链接工厂的对象
			Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
					.register("http", PlainConnectionSocketFactory.INSTANCE)
					.register("https", new SSLConnectionSocketFactory(sslContext)).build();
			connectManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
			// 设置连接池大小
			connectManager.setMaxTotal(300);
			connectManager.setDefaultMaxPerRoute(150);
			return connectManager;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private SSLConnectionSocketFactory createSSLConnSocketFactory() {
		try {
			SSLContext sslContext = new org.apache.http.ssl.SSLContextBuilder().build();
			return new SSLConnectionSocketFactory(sslContext, new String[] { "TLSv1" }, null,
					SSLConnectionSocketFactory.getDefaultHostnameVerifier());
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return null;
	}

	public static void doPostAsJson(String apiUrl, String requestParam) {
		HttpPost httpPost = new HttpPost(apiUrl);
		CloseableHttpResponse response = null;
		int statusCode = -1;
		CookieStore basicCookiestore = new BasicCookieStore();
		try {
			CloseableHttpClient httpclient = getHttpClient(fastRequestConfig, noRetryHandler, basicCookiestore);
			// 解决中文乱码问题
			StringEntity stringEntity = new StringEntity(requestParam, DEFAULT_ENCODING);
			stringEntity.setContentEncoding(DEFAULT_ENCODING);
			stringEntity.setContentType("text/plain");
			httpPost.setEntity(stringEntity);
			response = httpclient.execute(httpPost);
			statusCode = response.getStatusLine().getStatusCode();
			if (statusCode != HttpStatus.SC_OK) {
				log.error("上报失败,参数: {}", requestParam);
				return;
			}
		} catch (Exception e) {
			log.error("上报异常: ", e);
		} finally {
			if (response != null) {
				try {
					EntityUtils.consume(response.getEntity());
				} catch (IOException e) {
				}
			}
		}
	}

	private static CloseableHttpClient getHttpClient(RequestConfig requestConfig,
			HttpRequestRetryHandler httpRequestRetryHandler, CookieStore basicCookiestore) {
		return HttpClients.custom().setDefaultCookieStore(basicCookiestore).setSSLSocketFactory(connectFactory)
				.setConnectionManager(connManager).setDefaultRequestConfig(requestConfig)
				.setRetryHandler(httpRequestRetryHandler).build();
	}
}
